package app.delish.base.vm

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import app.delish.base.vm.MviViewModel.MviEvent
import app.delish.base.vm.MviViewModel.MviViewResult
import app.delish.base.vm.MviViewModel.MviViewState
import app.delish.base.vm.MviViewModel.MviSideEffect
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.scan
import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.launch

/**
 * MVI (Model-View-Intent) 架构的通用 ViewModel 基类
 *
 * 设计原理：
 * 将 UI 交互分解为四个核心组件：
 *   Event -> Result -> State -> Effect
 *
 * 使用协程 Flow 管理状态和事件，实现单向数据流
 *
 * 泛型参数：
 *  - Event: 用户交互事件（如按钮点击）
 *  - Result: 业务逻辑处理结果
 *  - State: UI 状态（可观察的 StateFlow）
 *  - Effect: 单次副作用（如导航、Toast消息）
 */
abstract class MviViewModel<Event : MviEvent, Result : MviViewResult, State : MviViewState, Effect : MviSideEffect>(
    initialState: State // 初始状态
) : ViewModel() {

    // 公开状态流（供 UI 层订阅）
    val states: StateFlow<State>

    // 公开副作用流（供 UI 层订阅）
    val effects: Flow<Effect>

    // 私有的事件流（内部处理）
    private val events = MutableSharedFlow<Event>()

    init {
        // 创建事件处理管道
        events
            .share() // 共享处理（避免重复订阅）
            .toResults() // 抽象方法：将事件转换为业务结果（子类实现）
            .share() // 再次共享
            .also { results ->
                // 分支1：处理为状态
                states = results.toStates(initialState)
                    .stateIn(
                        scope = viewModelScope,
                        started = SharingStarted.Lazily, // 惰性启动（只有订阅时才激活）
                        initialValue = initialState
                    )

                // 分支2：处理为副作用
                effects = results.toEffects() // 抽象方法：将结果转换为副作用
            }
    }

    /**
     * 处理外部事件（从UI层调用）
     */
    fun processEvent(event: Event) {
        viewModelScope.launch {
            events.emit(event) // 将事件发送到事件流
        }
    }

    /* 抽象方法 - 需子类实现 */

    /**
     * 转换事件流为业务结果流
     *
     * 子类实现要点：
     *  1. 处理各种UI事件（如按钮点击）
     *  2. 执行业务逻辑（如API调用）
     *  3. 将操作结果映射为对应的Result对象
     */
    protected abstract fun Flow<Event>.toResults(): Flow<Result>

    /**
     * 状态归约函数
     *
     * 子类实现要点：
     *  1. 接收当前状态和最新结果
     *  2. 返回基于结果更新后的新状态
     *  3. 必须为纯函数（无副作用）
     */
    protected abstract fun Result.reduce(state: State): State

    /**
     * 转换结果为副作用（可选实现）
     *
     * 默认返回空流，子类可重写以处理导航等一次性操作
     */
    protected open fun Flow<Result>.toEffects(): Flow<Effect> = emptyFlow()

    /* 辅助方法 */

    /**
     * 将结果流转换为状态流
     */
    private fun Flow<Result>.toStates(initialState: State): Flow<State> {
        // 使用scan操作符实现状态归约（类似Reducer）
        return scan(initialState) { state, result ->
            result.reduce(state) // 调用抽象reduce方法
        }
    }

    /**
     * Flow共享扩展（避免多次订阅时重复执行）
     */
    private fun <T> Flow<T>.share(): Flow<T> {
        return shareIn(
            scope = viewModelScope,
            started = SharingStarted.Eagerly // 立即开始共享
        )
    }

    /* MVI 组件标记接口（语义化接口）*/

    interface MviViewState   // UI状态
    interface MviSideEffect  // 单次副作用
    interface MviEvent       // 用户触发事件
    interface MviViewResult  // 业务处理结果
}